<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>代码执行顺序(Code execution order)</title>
    <!-- 
      JavaScript的代码执行顺序主要遵循以下几个原则：
      1. 顺序执行：
        - JavaScript代码默认是从上到下、从左到右顺序执行的。每一行代码执行完后，才会执行下一行。

      2. 函数调用：
        - 当遇到函数调用时，程序会跳转到函数内部执行该函数的代码，执行完毕后再返回到调用点继续执行后面的代码。

      3. 异步执行：
        - JavaScript是单线程的，但通过事件循环机制支持异步操作。
          异步操作（如 `setTimeout` 、 `Promise` 、 `async/await` 等）不会阻塞主线程，主线程会继续执行后续代码。
          当异步操作完成后，其回调函数会被放入任务队列，待主线程空闲时再执行。

      4. 变量提升：
        - 在JavaScript中，变量和函数的声明会被提升到作用域的顶部。这意味着可以在声明之前使用变量或函数，但变量的值不会被提升。例如：
          console.log(x); // 输出: undefined
          var x = 5;
          
      5. 作用域：
        - JavaScript使用词法作用域，函数的作用域在定义时确定，而不是在调用时。嵌套函数可以访问外部函数的变量。

      6. 闭包：
        - 闭包是指函数可以“记住”并访问其词法作用域，即使在函数外部被调用时。闭包可以用于数据封装和私有变量。

      7. 错误处理：
        - 当代码执行过程中发生错误时，JavaScript会抛出异常，除非在代码中使用 `try...catch` 语句来捕获和处理错误。

      8. 事件循环：
        - JavaScript引擎通过事件循环来处理异步操作。主线程执行同步代码，当遇到异步操作时，将其放入任务队列，
          当主线程空闲时，事件循环会从任务队列中取出异步操作的回调函数并执行。

      9. 微任务和宏任务：
        - 异步操作分为宏任务（如 `setTimeout` 、 `setInterval` 、 `I/O` 等）和微任务（如 `Promise` 、 `async/await` 等）。
          微任务会在当前事件循环的末尾执行，而宏任务会在下一个事件循环开始时执行。

      10. 模块化：
          - ES6引入了模块化机制，允许将代码分割成多个模块，每个模块有自己的作用域和执行顺序。

      11. 编译和解释：
          - JavaScript代码在执行前会经过编译阶段，编译器会将代码转换成可执行的字节码。然后，解释器会逐行解释和执行字节码。
          - 在编译阶段，JavaScript会进行变量提升、函数提升等操作。在解释阶段，JavaScript会处理异步操作、作用域、闭包等。
      
      12. 循环和条件语句：
          - `for` 、 `while` 、 `do...while` 、 `if...else` 等循环和条件语句会影响代码的执行顺序，它们会根据条件的真假来决定代码的执行路径。

      13. 异常处理：
          - `try...catch` 语句可以捕获和处理代码执行过程中的异常，避免程序崩溃。

      14. 代码块：
          - 使用 `{}` 包围的代码块会创建一个新的作用域，代码块内部的变量和函数只能在块内访问。

      总结来说，JavaScript的代码执行顺序是由顺序执行、函数调用、异步执行、变量提升、作用域、闭包和错误处理等多个方面共同决定的。
    -->
  </head>
  <body>
    <script>
      // 1.顺序执行
      console.log("顺序执行 Hello, World!");

      // 2.函数调用
      function greet(name) {
        console.log("函数调用 Hello, " + name + "!");
      }
      greet("Alice");

      // 3.异步执行
      setTimeout(function () {
        console.log("异步执行 This message is delayed.");
      }, 2000);

      function awaitFn() {
        console.log("异步执行This message is awaitFn.");
      }

      async function asyncFunction() {
        console.log("异步执行 This message is asynchronous.1");
        await awaitFn();
        console.log("异步执行 This message is asynchronous.2");
      }
      asyncFunction();

      // 4.变量提升
      var x = 5;
      console.log("变量提升", x);

      // 5.作用域
      function outer() {
        var outerVar = "变量提升 I am outer";
        function inner() {
          console.log(outerVar);
        }
        inner();
      }
      outer();

      // 6.闭包
      function createCounter() {
        var count = 0;
        return function () {
          count++;
          console.log("闭包", count);
        };
      }
      var counter = createCounter();
      counter(); // 输出: 1
      counter(); // 输出: 2

      // 7.错误处理
      // try {
      //   console.log(nonExistentVariable);
      // } catch (error) {
      //   console.error("An error occurred:", error.message);
      // }

      // 8.事件循环
      setTimeout(function () {
        console.log("事件循环 This message is delayed.");
      }, 2000);

      function foo(b) {
        let a = 10;
        return a + b + 11;
      }

      function bar(x) {
        let y = 3;
        return foo(x * y);
      }

      console.log("事件循环", bar(7)); // 返回 42

      // 9.微任务和宏任务
      Promise.resolve().then(function () {
        console.log("微任务和宏任务 This message is a microtask.");
      });
      setTimeout(function () {
        console.log("微任务和宏任务 This message is a macrotask.");
      });
      // 10.模块化
      // import { module1, module2 } from './module.js';

      // 11.编译和解释
      // - JavaScript代码在执行前会经过编译阶段，编译器会将代码转换成可执行的字节码。然后，解释器会逐行解释和执行字节码。
      // - 在编译阶段，JavaScript会进行变量提升、函数提升等操作。在解释阶段，JavaScript会处理异步操作、作用域、闭包等。

      // 12.循环和条件语句
      let isLogin = true;
      if (isLogin) {
        console.log("编译和解释 Welcome back!");
      } else {
        console.log("编译和解释 Please log in.");
      }

      let i = 0;
      while (i < 5) {
        console.log(i);
        i++;
      }

      // 13.异常处理
      try {
        throw new Error("异常处理 Something went wrong!");
      } catch (error) {
        console.error("异常处理 An error occurred:", error.message);
      }

      // 14. 代码块
      {
        let x = 10;
        console.log(x); // 输出: 10
      }
      // console.log(x); // ReferenceError: x is not defined

      // 15.函数
      function add(a, b) {
        return a + b;
      }
      console.log(add(2, 3)); // 输出: 5
    </script>
  </body>
</html>
